package com.teradata.singleton.register;

/**
 * 第六种（枚举）：
 * 这种方式是Effective Java作者Josh Bloch 提倡的方式，
 * 它不仅能避免多线程同步问题，而且还能防止反序列化重新创建新的对象，
 * 可谓是很坚强的壁垒啊，不过，个人认为由于1.5中才加入enum特性，
 * 用这种方式写不免让人感觉生疏，在实际工作中，我也很少看见有人这么写过。
 *
 * 传统的两私有一公开（私有构造方法、私有静态实例(懒实例化/直接实例化)、公开的静态获取方法）
 * 涉及线程安全问题（即使有多重检查锁也可以通过反射破坏单例），
 * 目前最为安全的实现单例的方法是通过内部静态enum的方法来实现，
 * 因为JVM会保证enum不能被反射并且构造器方法只执行一次。
 */
public class EnumSingleton {

    //1.私有化空参构造方法
    private EnumSingleton(){}

    //2.构建一个枚举类型，枚举类型本身就是静态的，所以static关键字为灰色，可以不写
    private static enum SingletonEnum{
        //2.1 枚举成员为INSTANCE
        INSTANCE;
        //2.2 为枚举类型指定私有化成员类型
        private EnumSingleton singleton;
        //2.3 在枚举空构造函数中构建单例类的实例
        // 枚举的构造函数强制就是私有的，所以private关键字为灰色。JVM会保证此方法绝对只调用一次
        private SingletonEnum(){
            singleton = new EnumSingleton();
        }
        //2.4 为枚举类型创建一个公开public普通方法，返回单例类的实体
        public EnumSingleton getInstance(){
            return singleton;
        }
    }

    //3.为单例类构建静态方法，从枚举中获取单例类的实例
    public static EnumSingleton getInstance(){
        return SingletonEnum.INSTANCE.getInstance();
    }

}
